/**
 * 
 */
package com.zhiteng.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.zhiteng.entity.AdjustBill;
import com.zhiteng.entity.Bill;
import com.zhiteng.entity.LeaveBill;
import com.zhiteng.entity.Procdef;
import com.zhiteng.entity.Procins;
import com.zhiteng.entity.Teacher;
import com.zhiteng.mapper.LeaveMapper;
import com.zhiteng.mapper.ProcinsMapper;
import com.zhiteng.service.LeaveService;
import com.zhiteng.service.ProcessService;
import com.zhiteng.service.SmartCampusApiService;
import com.zhiteng.service.TeacherService;

import tk.mybatis.mapper.entity.Example;
import tk.mybatis.mapper.entity.Example.Criteria;

/**
 * <p>
 * Title: LeaveServiceImpl.java
 * </p>
 * <p>
 * Description:请假单Service
 * </p>
 * 
 * @author dragon
 * @date 2018年12月1日
 * @version 1.0
 */
@Service
public class LeaveServiceImpl implements LeaveService {
	@Autowired
	private LeaveMapper leaveMapper;
	@Autowired
	private ProcessService processService;
	@Autowired
	private ProcinsMapper procinsMapper;
	@Autowired
	private SmartCampusApiService smartCampusApiService;
	@Autowired
	private TeacherService teacherService;

	@Override
	public void saveLeaveBill(LeaveBill bill, List<Procdef> procdefList) {
		// 保存请假单
		leaveMapper.insert(bill);
		// 创建并保存请假的流程实例
		saveLeaveProcess(bill, procdefList);
	}

	// 创建请假的流程实例
	private void saveLeaveProcess(LeaveBill bill, List<Procdef> procdefList) {
		// ps:传参过来的procdefList是sort by sequence asc排序好的
		double hours = bill.getTotal_hour(); // 请假小时数
		// 根据请假的小时数查询该教师需要走的审批流程（需要哪些人审批）
		List<Procins> procinsList = new ArrayList<>();
		for (int i = 0; i < procdefList.size(); i++) {
			Procins procins = new Procins();
			procins.setType(1); // 请假流程
			procins.setComplated(0);
			procins.setBill_id(bill.getId());
			procins.setSchool_id(bill.getSchool_id());
			procins.setTeacher_id(bill.getTeacher_id());
			procins.setAssignee_id(procdefList.get(i).getAssignee_id());
			procins.setSequence(procdefList.get(i).getSequence());
			if (i == 0) { // 第一个审批人的开始时间就是流程创建（发起流程）的时间
				procins.setStart(new Date());
			}
			procinsList.add(procins);
			if (i + 1 < procdefList.size() && hours > procdefList.get(i).getHours()
					&& hours <= procdefList.get(i + 1).getHours()) {
				break;
			}
		}
		// 保存请假的流程实例
		processService.saveProcinsBatch(procinsList);
		// 此处要给第一个审批人发送消息，提示审批(放到controller层了)
		/*String assigneeId = procdefList.get(0).getAssignee_id(); 
		Teacher teacher = teacherService.queryTeacherById(assigneeId); 
		Map<String,String> data = new HashMap<>(); 
		data.put("wxuserid", teacher.getWxuserid()); 
		data.put("content",bill.getTeacherName()+"的请假单待你确认");
		smartCampusApiService.sendMsg(bill.getSchool_id(), data);*/
		 
	}

	// 查询我的所有请假申请
	@Override
	public List<LeaveBill> queryLeaveBillsByTeacherIdAndSchoolId(String teacherId, String schoolId) {
		LeaveBill leaveBill = new LeaveBill();
		leaveBill.setTeacher_id(teacherId);
		leaveBill.setSchool_id(schoolId);
		return leaveMapper.select(leaveBill);
	}

	@Override
	public LeaveBill queryLeaveBillById(long billId) {
		return leaveMapper.selectByPrimaryKey(billId);
	}

	@Override
	public void updateLeaveBillByRecord(LeaveBill bill) {
		leaveMapper.updateByPrimaryKeySelective(bill);
	}

	@Override
	public List<LeaveBill> queryMyUncomplatedLeaveBills(String teacherId, String schoolId) {
		List<LeaveBill> uncomplatedLeaveBillList = new ArrayList<>(); // 用来存放待我确认的请假单
		
		//	查询待我确认的流程实例
		Example example = new Example(Procins.class);
		Criteria criteria = example.createCriteria();
		criteria.andEqualTo("assignee_id", teacherId);
		criteria.andEqualTo("school_id", schoolId);
		criteria.andEqualTo("type", 1);
		criteria.andIsNotNull("start");
		criteria.andIsNull("end");
		List<Procins> procinsList = procinsMapper.selectByExample(example);
		for (Procins procins : procinsList) {
			LeaveBill bill = leaveMapper.selectByPrimaryKey(procins.getBill_id());
			uncomplatedLeaveBillList.add(bill);
		}
		
		return uncomplatedLeaveBillList;
	}

	@Override
	public void saveComplatedMyLeaveBill(long billId, String teacherId, String schoolId, int status, String remark) {
		// ps:billId + type + teacherId(审批人id)能唯一确定tb_procins中一条记录（一个流程实例包含多条记录）
		Procins record = new Procins();
		record.setBill_id(billId);
		record.setSchool_id(schoolId);
		record.setAssignee_id(teacherId);
		record.setType(1); // 请假单
		List<Procins> procinsList = processService.queryProcinsByRecord(record); // 该查询最多只有一条结果
		if (procinsList == null || procinsList.isEmpty()) {
			// return ZTResult.result(1,"审批失败，未查询到该请假流程");
			return;
		}
		Procins procins = procinsList.get(0);
		Date end = new Date();
		procins.setEnd(end);
		if (StringUtils.isNoneBlank(remark))
			procins.setRemark(remark);

		LeaveBill bill = queryLeaveBillById(billId);
		if (bill.getRevocable() == 0) { // 只要有一个人审批了，不论同意还是不同意，就设置为不可撤销
			bill.setRevocable(1);
		}
		// 申请请假的教师
		Teacher teacher = teacherService.queryTeacherById(bill.getTeacher_id());
		String wxuserid = teacher.getWxuserid();

		// 判断是不是最后一个审批人：type+billId+sequence唯一确定一条Procins记录
		Procins record2 = new Procins();
		record2.setType(1);
		record2.setBill_id(billId);
		record2.setSequence(procins.getSequence() + 1); // 下一个审批人
		List<Procins> pList = processService.queryProcinsByRecord(record2); // 查询下一个审批人对应的Procins,结果只能是0个或1个

		if (status == 0) { // 审批通过：需要更新请假单和对应的所有Procins
			procins.setStatus(0); // 同意
			/*
			 * 两种情况： （1）我是最后一个审批人：流程结束，请假单审批通过 （2）我不是最后一个审批人：流程未结束
			 */
			processService.updateProcinsByRecord(procins);
			if (pList == null || pList.isEmpty()) { // 是最后一个审批人
				// 1、修改请假单和流程实例（此请假单相关的所有Procins记录）
				bill.setStatus(1);

				Procins record3 = new Procins();
				record3.setBill_id(billId);
				record3.setType(1);
				List<Procins> procinsList1 = processService.queryProcinsByRecord(record3);
				for (Procins p : procinsList1) {
					p.setComplated(1); // 审批通过
				}
				// 2、更新请假单和流程实例到数据库
				updateLeaveBillByRecord(bill);
				processService.updateProcinsBatch(procinsList);
				processService.updateProcinsBatch(procinsList1);
				// 3、推送通知
				Map<String,String> data = new HashMap<>(); 
				data.put("wxuserid", wxuserid);
				data.put("content", "请假单已审批通过"); 
				smartCampusApiService.sendMsg(schoolId,data);
				
				// 4、奖励积分
				teacherService.updateBonusPoint(teacher.getUserid(),1);
				 
			} else { // 不是最后一个审批人
				// 设置下一个人的审批开始时间（与上一个人的审批结束时间相同）
				pList.get(0).setStart(end);
				processService.updateProcinsByRecord(pList.get(0));
				updateLeaveBillByRecord(bill);
				
				// 给下一个审批人推送通知
				Teacher t = teacherService.queryTeacherById(pList.get(0).getAssignee_id());
				Map<String,String> data = new HashMap<>(); 
				data.put("wxuserid", t.getWxuserid());
				data.put("content", bill.getTeacher_id()+"的请假单待你审批"); 
				smartCampusApiService.sendMsg(schoolId,data);
			}
		} else { // 审批拒绝：需要更新请假单和对应的所有Procins
			// 1、修改请假单和流程实例
			procins.setStatus(1); // 拒绝
			processService.updateProcinsByRecord(procins);

			bill.setStatus(2); // 审批被驳回
			// 查询出一个请假流程实例中的所有Procins
			Procins record3 = new Procins();
			record3.setBill_id(billId);
			record3.setType(1);
			List<Procins> procinsList1 = processService.queryProcinsByRecord(record3);
			for (Procins p : procinsList1) {
				p.setComplated(2); // 审批被驳回
			}

			// 2、更新请假单和流程实例到数据库
			updateLeaveBillByRecord(bill);
			processService.updateProcinsBatch(procinsList);

			// 3、推送通知
			Map<String,String> data = new HashMap<>(); 
			data.put("wxuserid", wxuserid);
			data.put("content", "请假单被驳回"); 
			smartCampusApiService.sendMsg(schoolId, data);
			 
		}
	}

	@Override
	public List<Bill> queryMyComplatedLeaveBill(String teacherId, String schoolId) {
		List<Procins> procinsList = processService.queryComplatedProcinsByAssigneeId(teacherId, schoolId);
		List<Bill> billList = new ArrayList<>();
		if (procinsList == null || procinsList.isEmpty()) {
			// return ZTResult.result(0, "未查询到我已确认的请假单");
			return billList;
		}
		for (Procins procins : procinsList) {
			LeaveBill leaveBill = queryLeaveBillById(procins.getBill_id());
			Bill bill = new Bill(leaveBill.getCreateDate());
			bill.setType(1);
			bill.setId(leaveBill.getId());
			bill.setTeacherName(leaveBill.getTeacherName());
			bill.setReason(leaveBill.getReason());
			bill.setStart(leaveBill.getStart());
			bill.setEnd(leaveBill.getEnd());
			bill.setHours(leaveBill.getTotal_hour());
			bill.setIsAgree(procins.getStatus()); // 已同意/已拒绝

			billList.add(bill);
		}
		return billList;
	}

	@Override
	public void updateCancleLeaveBill(LeaveBill leaveBill) {
		// 撤回请假申请：1.修改leaveBill状态为已撤回 2.删除流程实例 3.通知第一个审批人已撤回
		leaveMapper.updateByPrimaryKeySelective(leaveBill);
		List<Procins> procinsList = processService.queryProcinsByBillId(leaveBill.getId()); // sequence升序
		if (procinsList != null && !procinsList.isEmpty()) {
			String assigneeId = procinsList.get(0).getAssignee_id();
			Teacher teacher = teacherService.queryTeacherById(assigneeId);
			processService.deleteProcinsBybillIdAndType(leaveBill.getId(), 1);
			// 推送通知
			Map<String,String> data = new HashMap<>(); 
			data.put("wxuserid",teacher.getWxuserid()); 
			data.put("content",leaveBill.getTeacherName()+"的请假单已撤回");
			smartCampusApiService.sendMsg(leaveBill.getSchool_id(), data);
		}
	}

	@Override
	public List<LeaveBill> queryLeaveBySchoolIdAndStatus(String schoolId, int i) {
		LeaveBill record = new LeaveBill();
		record.setSchool_id(schoolId);
		record.setStatus(i);
		return leaveMapper.select(record);
	}

	@Override
	public List<LeaveBill> queryLeaveBySchoolIdAndStatusAndQJ(String schoolId, int i, Date startTime3, Date endTime3) {
		Example example = new Example(LeaveBill.class);

		Criteria criteria = example.createCriteria();
		criteria.andEqualTo("school_id", schoolId);
		criteria.andEqualTo("status", i);
		criteria.andBetween("start", startTime3, endTime3);
		return leaveMapper.selectByExample(example);
	}

	@Override
	public List<LeaveBill> queryLeaveBySchoolIdAndStatusAndQJAndTeacherId(String schoolId, String teacherId, int i,
			Date startTime3, Date endTime3) {
		Example example = new Example(LeaveBill.class);

		Criteria criteria = example.createCriteria();
		criteria.andEqualTo("school_id", schoolId);
		criteria.andEqualTo("teacher_id", teacherId);
		criteria.andEqualTo("status", i);
		criteria.andBetween("start", startTime3, endTime3);
		return leaveMapper.selectByExample(example);
	}
}
